#include"mystdio.h"
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<assert.h>

//fopen("a/b/c","w");
//打开文件            文件的名字       打开方式
MY_FILE* my_fopen(const char*path,const char*mode)
{
  //设置打开方式，调用open
  int flag=0;
  if(strcmp(mode,"r")==0)
  {
    flag|=O_RDONLY;
  }
  else if(strcmp(mode,"w")==0)
  {
    flag|=(O_WRONLY | O_CREAT | O_TRUNC);
  }
  else if(strcmp(mode,"a")==0)
  {
    flag|=(O_WRONLY | O_TRUNC | O_APPEND);
  }

  //设置默认打开文件的权限
  mode_t m=0666;//八进制

  //使用open打开文件
  int fd=0;
  if(flag & O_CREAT)
  {
    //创建文件需要指明权限
    fd=open(path,flag,m);
  }
  else 
  {
    fd=open(path,flag);
  }

  if(fd<0)
  {
    //创建失败
    return NULL;
  }

  //给用户返回MY_FILE对象
  MY_FILE*mf=(MY_FILE*)malloc(sizeof(MY_FILE));
  if(mf==NULL)
  {
    //malloc失败
    //要关闭文件
    close(fd);
    return NULL;
  }

  //初始化MY_FILE
  mf->fd=fd;
  //先默认为行刷新
  mf->flags=0;
  mf->flags |= BUFF_LINE;
  
  //初始化缓冲区
  memset(mf->outputbuffer,'\0',sizeof(mf->outputbuffer));
  mf->current=0;

  //返回MY_FILE
  return mf;

}

//写入文件        写入内容     每个元素的大小  多少个元素   指定文件
//这里将返回值设置为返回实际写入缓冲区的字节数
size_t my_fwrite(const void*ptr,size_t size,size_t nmemb,MY_FILE*stream)
{
  //缓冲区满了，就直接写入
  if(stream->current==NUM)
  {
    my_fflush(stream);
  }

  //缓冲区没满，要根据写入数据数量和缓冲区剩余大小
  //进行数据拷贝即可
  
  //要写入多少
  size_t user_size=size*nmemb;
  //缓冲区还有多少
  size_t my_size=NUM-stream->current;

  size_t writen=0;//返回值
  if(my_size>=user_size)
  {
    //空间足够
    //            拷贝哪里                   从哪拷贝  拷多少
    memcpy(stream->outputbuffer+stream->current,ptr,user_size);

    stream->current+=user_size;
    writen=user_size;
  }
  else
  {
    memcpy(stream->outputbuffer+stream->current,ptr,my_size);
    stream->current=NUM;
    writen=my_size;
  }
  
  //开始计划刷新
  if(stream->flags&BUFF_ALL)
  {
    //全刷新
    if(stream->current==NUM)
    {
      my_fflush(stream);
    }
  }
  else if(stream->flags & BUFF_LINE)
  {
    //行刷新
    if(stream->outputbuffer[stream->current-1]=='\n')
    {
      my_fflush(stream);
    }
  }

  return writen;
}


//刷新缓冲区
int my_fflush(MY_FILE*fp)
{
  assert(fp);
  
  write(fp->fd,fp->outputbuffer,fp->current);
  fp->current=0;

  return 0;
}


//关闭文件
int my_fclose(MY_FILE* fp)
{
  //传进来的MY_FILE指针不能为空
  assert(fp);  

  //1.冲刷缓冲区
  if(fp->current>0)
  {
    my_fflush(fp);
  }

  //2.关闭文件
  close(fp->fd);

  //3.释放MY_FILE结构体空间
  free(fp);

  //4.将MY_FILE指针置为空
  fp=NULL;
  
  return 0;
}
